#include <stdbool.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>
#include <esp_timer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

// display
#include "esp_lcd_panel_ops.h"
// #include "esp_lcd_mipi_dsi.h"
#include "esp_ldo_regulator.h"
// #include "esp_lcd_jd9365_10_1.h"

#include <esp_lcd_panel_vendor.h>
#include <driver/spi_common.h>
#include <esp_lcd_gc9a01.h>
// touch
#include "esp_lcd_touch_gt911.h"
#include <driver/i2c_master.h>

// lvgl
#include <lvgl.h>
#include <esp_lvgl_port.h>
#include "ui_header.h"
// 添加 LVGL GIF 支持
#if LV_USE_GIF
#include "src/libs/gif/lv_gif.h"
#endif

// 添加视频编解码器支持
#include "esp_heap_caps.h"
#include "esp_system.h"
#include "esp_video_enc.h"
#include "esp_video_dec.h"
#include "video_codec_test_utils.h"
#include "esp_video_dec_reg.h"
#include "esp_video_enc_reg.h"
#include "esp_video_codec_utils.h"
#include "esp_video_enc_default.h"
#include "esp_video_dec_default.h"
#include "esp_video_codec_version.h"

// log
#include <esp_log.h>

// sd card
// #include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
// #include "sd_test_io.h"
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif
//文件系统
#include "esp_spiffs.h"


// define
#define TAG "WaveshareEsp32p4xc"

// SD卡性能测试相关定义
#define SD_TEST_FILE_SIZE_KB 1024  // 测试文件大小：1MB
#define SD_TEST_BUFFER_SIZE 4096   // 4KB缓冲区
#define SD_TEST_FILE_PATH "/sdcard/test.bin"
#define GIF_FILE_PATH "/spiffs/Angry.gif"  // GIF文件路径
#define LVGL_GIF_FILE_PATH "spiffs/Angry.gif"  // LVGL GIF文件路径

#define SPIFFS_PATH "//spiffs"
// GIF播放相关变量
static esp_timer_handle_t gif_timer_handle = NULL;
static lv_obj_t *gif_img1 = NULL;
static lv_obj_t *gif_img2 = NULL;
static uint8_t *gif_data1 = NULL;
static uint8_t *gif_data2 = NULL;
static size_t gif_data_size = 0;
extern lv_display_t *display1_ ;
extern lv_display_t *display2_ ;
extern lv_obj_t *screen1_;
extern lv_obj_t *screen2_;

/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////Display/////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define AUDIO_CODEC_I2C_SDA_PIN  GPIO_NUM_7
#define AUDIO_CODEC_I2C_SCL_PIN  GPIO_NUM_8

// #define LCD_BIT_PER_PIXEL          (16)
// #define PIN_NUM_LCD_RST            GPIO_NUM_27

#define DELAY_TIME_MS                      (3000)
// #define LCD_MIPI_DSI_LANE_NUM          (2)    // 2 data lanes

// #define MIPI_DSI_PHY_PWR_LDO_CHAN          (3)
// #define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV    (2500)

// #define DISPLAY_SWAP_XY false
// #define DISPLAY_MIRROR_X false
// #define DISPLAY_MIRROR_Y false

// #define DISPLAY_OFFSET_X  0
// #define DISPLAY_OFFSET_Y  0

// #define DISPLAY_BACKLIGHT_PIN GPIO_NUM_26
// #define DISPLAY_BACKLIGHT_OUTPUT_INVERT true

// #define DISPLAY_WIDTH 800
// #define DISPLAY_HEIGHT 800

// static esp_lcd_panel_io_handle_t io = NULL;
// static esp_lcd_panel_handle_t disp_panel = NULL;
// static lv_display_t *display_ = NULL;
// static lv_obj_t *screen = NULL;
// static i2c_master_bus_handle_t i2c_bus_ = NULL;

// 颜色数组
static const uint32_t colors[] = {
    0x000000,  // 黑色
    0xFF0000,  // 红色
    0x00FF00,  // 绿色
    0x0000FF,  // 蓝色
    0xFFFF00,  // 黄色
    0xFF00FF,  // 洋红色
    0x00FFFF,  // 青色
    0xFFFFFF,  // 白色
    0xFF8000,  // 橙色
    0x8000FF,  // 紫色
};
static const int color_count = sizeof(colors) / sizeof(colors[0]);

// 读取GIF文件到内存
static esp_err_t load_gif_file(void)
{
    FILE *f = fopen(GIF_FILE_PATH, "rb");
    if (f == NULL) {
        ESP_LOGE(TAG, "无法打开GIF文件: %s", GIF_FILE_PATH);
        return ESP_FAIL;
    }

    // 获取文件大小
    fseek(f, 0, SEEK_END);
    gif_data_size = ftell(f);
    fseek(f, 0, SEEK_SET);

    if (gif_data_size == 0) {
        ESP_LOGE(TAG, "GIF文件为空");
        fclose(f);
        return ESP_FAIL;
    }

    // 分配内存
    gif_data1 = malloc(gif_data_size);
    if (gif_data1 == NULL) {
        ESP_LOGE(TAG, "无法分配内存用于GIF数据，大小: %zu", gif_data_size);
        fclose(f);
        return ESP_FAIL;
    }

    // 读取文件内容
    size_t bytes_read = fread(gif_data1, 1, gif_data_size, f);
    fclose(f);

    if (bytes_read != gif_data_size) {
        ESP_LOGE(TAG, "读取GIF文件失败，期望: %zu, 实际: %zu", gif_data_size, bytes_read);
        free(gif_data1);
        gif_data1 = NULL;
        return ESP_FAIL;
    }

    ESP_LOGI(TAG, "成功读取GIF文件，大小: %zu 字节", gif_data_size);
    return ESP_OK;
}

// GIF播放定时器回调函数（仅用于颜色动画）
static void gif_timer_callback(void* arg)
{
    static int color_index = 0;
    
    if (gif_img1 != NULL) {
        // 检查是否为标签对象（显示 GIF 信息）
        if (lv_obj_check_type(gif_img1, &lv_label_class)) {
            // 这是显示GIF信息的标签，不需要动画
            return;
        }
        
#if LV_USE_GIF
        // 检查是否为 GIF 对象
        if (lv_obj_check_type(gif_img1, &lv_gif_class)) {
            // 这是 GIF 对象，LVGL 会自动处理动画，不需要手动操作
            return;
        }
#endif
        
        // 这是颜色动画对象，切换颜色
        color_index = (color_index + 1) % color_count;
        lv_obj_set_style_bg_color(gif_img1, lv_color_hex(colors[color_index]), 0);
        ESP_LOGI(TAG, "动画颜色切换到: 0x%06X", (unsigned int)colors[color_index]);
    }
}

// 启动GIF播放器
static void start_gif_player(lv_obj_t * screen, const char *gif_file_path, uint8_t img_index)
{
    // 首先检查GIF文件是否存在
    FILE *f = fopen(gif_file_path, "rb");
    if (f == NULL) {
        ESP_LOGE(TAG, "无法找到GIF文件: %s，创建一个简单的动画显示", gif_file_path);
        
        // 如果没有GIF文件，创建一个简单的颜色动画
        
        
        // 创建定时器以实现颜色动画效果
        const esp_timer_create_args_t timer_args = {
            .callback = &gif_timer_callback,
            .arg = NULL,
            .name = "gif_timer"
        };
        
        esp_err_t err = esp_timer_create(&timer_args, &gif_timer_handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "创建定时器失败: %s", esp_err_to_name(err));
            return;
        }
        
        // 启动定时器，每1000毫秒触发一次
        err = esp_timer_start_periodic(gif_timer_handle, 1000000);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "启动定时器失败: %s", esp_err_to_name(err));
            esp_timer_delete(gif_timer_handle);
            gif_timer_handle = NULL;
            return;
        }
        
        ESP_LOGI(TAG, "颜色动画启动成功");
        
    } else {
        fclose(f);
        
#if LV_USE_GIF
        ESP_LOGI(TAG, "LVGL GIF 支持已启用，创建 GIF 对象");
        lv_obj_t* gif_img = NULL;
        if(img_index == 0)
        {
            gif_img = gif_img1;
        }else
        {
            gif_img = gif_img2;
        }
        
        // 创建 LVGL GIF 对象
        gif_img = lv_gif_create(screen);
        if (gif_img == NULL) {
            ESP_LOGE(TAG, "创建 GIF 对象失败");
            return;
        }
        
        // 设置 GIF 文件路径
        ESP_LOGI(TAG, "尝试设置GIF源文件: %s", gif_file_path);
        lv_gif_set_src(gif_img, gif_file_path);
        
        // 检查GIF是否成功加载
        if (lv_gif_is_loaded(gif_img)) {
            ESP_LOGI(TAG, "GIF加载成功！");
            
            // 居中显示 GIF
            lv_obj_center(gif_img);
            
            // 设置可见性
            lv_obj_clear_flag(gif_img, LV_OBJ_FLAG_HIDDEN);

            ESP_LOGI(TAG, "GIF 文件已加载并开始播放: %s", gif_file_path);
            // fclose(f);
        } else {
            ESP_LOGE(TAG, "GIF加载失败！文件路径: %s", LVGL_GIF_FILE_PATH);
            
            // 尝试不同的路径格式
            ESP_LOGI(TAG, "尝试使用无驱动器前缀的路径: %s", GIF_FILE_PATH);
            lv_gif_set_src(gif_img, GIF_FILE_PATH);
            
            if (lv_gif_is_loaded(gif_img)) {
                ESP_LOGI(TAG, "使用无前缀路径加载GIF成功！");
                // lv_obj_center(gif_img);
                lv_obj_clear_flag(gif_img, LV_OBJ_FLAG_HIDDEN);
            } else {
                ESP_LOGE(TAG, "两种路径格式都无法加载GIF文件");
                
                // 如果GIF加载失败，创建一个错误信息显示
                lv_obj_del(gif_img);
                gif_img = lv_label_create(screen);
                lv_label_set_text(gif_img, "GIF file load failed\nPlease check:\n1. File exists\n2. File format is correct");
                lv_obj_center(gif_img);
                lv_obj_set_style_text_color(gif_img, lv_color_white(), 0);
                lv_obj_set_style_text_align(gif_img, LV_TEXT_ALIGN_CENTER, 0);
            }
        }
        
#else
        ESP_LOGW(TAG, "LVGL GIF 支持未启用，显示文件信息");
        
        // 读取GIF文件（用于显示信息）
        if (load_gif_file() != ESP_OK) {
            ESP_LOGE(TAG, "加载GIF文件失败");
            return;
        }

        // 创建一个标签显示GIF信息
        lv_obj_t * gif_img = lv_label_create(screen);
        if (gif_img == NULL) {
            ESP_LOGE(TAG, "创建标签对象失败");
            free(gif_data);
            gif_data = NULL;
            return;
        }
        
        // 显示GIF文件信息
        char info_text[200];
        snprintf(info_text, sizeof(info_text), 
                "发现GIF文件!\n"
                "文件路径: %s\n"
                "文件大小: %zu 字节\n"
                "注意: LVGL GIF支持未启用", 
                GIF_FILE_PATH, gif_data_size);
        
        lv_label_set_text(gif_img, info_text);
        lv_obj_center(gif_img);
        lv_obj_set_style_text_align(gif_img, LV_TEXT_ALIGN_CENTER, 0);
        lv_obj_set_style_text_color(gif_img, lv_color_white(), 0);
        
        ESP_LOGI(TAG, "显示GIF文件信息");
#endif
    }
    
    ESP_LOGI(TAG, "GIF播放器启动成功");
}

// 停止GIF播放器
static void stop_gif_player(uint8_t img_index)
{
    if (gif_timer_handle != NULL) {
        esp_timer_stop(gif_timer_handle);
        esp_timer_delete(gif_timer_handle);
        gif_timer_handle = NULL;
        ESP_LOGI(TAG, "动画定时器已停止");
    }
    lv_obj_t * gif_img = NULL;
    if(img_index == 0)
    {
       gif_img = gif_img1;
    }else
    {
        gif_img = gif_img2;
    }
    if (gif_img != NULL) {
#if LV_USE_GIF
        if (lv_obj_check_type(gif_img, &lv_gif_class)) {
            ESP_LOGI(TAG, "正在删除 GIF 对象");
        } else {
            ESP_LOGI(TAG, "正在删除其他显示对象");
        }
#endif
        lv_obj_del(gif_img);
        gif_img = NULL;
    }
    
    if (gif_data1 != NULL) {
        free(gif_data1);
        gif_data1 = NULL;
        gif_data_size = 0;
        ESP_LOGI(TAG, "GIF数据内存已释放");
    }
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////SD Card/////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define MOUNT_POINT "/sdcard"

// SD卡全局变量
static sdmmc_card_t *g_sd_card = NULL;
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
static sd_pwr_ctrl_handle_t g_pwr_ctrl_handle = NULL;
#endif

#ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS
const char* names[] = {"CLK", "CMD", "D0", "D1", "D2", "D3"};
const int pins[] = {CONFIG_EXAMPLE_PIN_CLK,
                    CONFIG_EXAMPLE_PIN_CMD,
                    CONFIG_EXAMPLE_PIN_D0
                    #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
                    ,CONFIG_EXAMPLE_PIN_D1,
                    CONFIG_EXAMPLE_PIN_D2,
                    CONFIG_EXAMPLE_PIN_D3
                    #endif
                    };

const int pin_count = sizeof(pins)/sizeof(pins[0]);

#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE
const int adc_channels[] = {CONFIG_EXAMPLE_ADC_PIN_CLK,
                            CONFIG_EXAMPLE_ADC_PIN_CMD,
                            CONFIG_EXAMPLE_ADC_PIN_D0
                            #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
                            ,CONFIG_EXAMPLE_ADC_PIN_D1,
                            CONFIG_EXAMPLE_ADC_PIN_D2,
                            CONFIG_EXAMPLE_ADC_PIN_D3
                            #endif
                            };
#endif //CONFIG_EXAMPLE_ENABLE_ADC_FEATURE

pin_configuration_t config = {
    .names = names,
    .pins = pins,
#if CONFIG_EXAMPLE_ENABLE_ADC_FEATURE
    .adc_channels = adc_channels,
#endif
};
#endif //CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS
#define EXAMPLE_MAX_CHAR_SIZE    64



////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////LOG/////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////



    static esp_err_t bsp_enable_dsi_phy_power(void) {
#if MIPI_DSI_PHY_PWR_LDO_CHAN > 0
        // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
        static esp_ldo_channel_handle_t phy_pwr_chan = NULL;
        esp_ldo_channel_config_t ldo_cfg = {
            .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN,
            .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
        };
        esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan);
        ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0

        return ESP_OK;
    }
static esp_err_t s_example_write_file(const char *path, char *data)
{
    // FUNC_TIME_START(s_example_write_file);
    // ESP_LOGI(TAG, "Opening file %s", path);
    // FILE *f = fopen(path, "w");
    // if (f == NULL) {
    //     ESP_LOGE(TAG, "Failed to open file for writing");
    //     return ESP_FAIL;
    // }
    // fprintf(f, "%s", data);
    // fclose(f);
    // ESP_LOGI(TAG, "File written");
    // FUNC_TIME_END(s_example_write_file);
    return ESP_OK;
}

static esp_err_t s_example_read_file(const char *path)
{
    // FUNC_TIME_START(s_example_read_file);
    // ESP_LOGI(TAG, "Reading file %s", path);
    // FILE *f = fopen(path, "r");
    // if (f == NULL) {
    //     ESP_LOGE(TAG, "Failed to open file for reading");
    //     return ESP_FAIL;
    // }
    // char line[EXAMPLE_MAX_CHAR_SIZE];
    // fgets(line, sizeof(line), f);
    // fclose(f);

    // // strip newline
    // char *pos = strchr(line, '\n');
    // if (pos) {
    //     *pos = '\0';
    // }
    // ESP_LOGI(TAG, "Read from file: '%s'", line);
    // FUNC_TIME_END(s_example_read_file);
    return ESP_OK;
}

// SD卡写入速度测试
static void sd_write_speed_test(void)
{
    // ESP_LOGI(TAG, "=== SD卡写入速度测试开始 ===");
    
    // // 检查SD卡是否仍然挂载
    // if (g_sd_card == NULL) {
    //     ESP_LOGE(TAG, "SD卡未挂载，无法进行写入测试");
    //     return;
    // }
    
    // // 检查挂载点是否存在
    // struct stat st;
    // if (stat(MOUNT_POINT, &st) != 0) {
    //     ESP_LOGE(TAG, "挂载点 %s 不存在", MOUNT_POINT);
    //     return;
    // }
    
    // ESP_LOGI(TAG, "SD卡状态检查通过，开始性能测试");
    // ESP_LOGI(TAG, "测试文件路径: %s", SD_TEST_FILE_PATH);
    
    // uint8_t *test_buffer = malloc(SD_TEST_BUFFER_SIZE);
    // if (test_buffer == NULL) {
    //     ESP_LOGE(TAG, "内存分配失败");
    //     return;
    // }
    
    // // 填充测试数据（二进制模式）
    // for (int i = 0; i < SD_TEST_BUFFER_SIZE; i++) {
    //     test_buffer[i] = i & 0xFF;
    // }
    
    // ESP_LOGI(TAG, "尝试创建文件: %s", SD_TEST_FILE_PATH);
    // FILE *f = fopen(SD_TEST_FILE_PATH, "wb");
    // if (f == NULL) {
    //     ESP_LOGE(TAG, "无法创建测试文件 %s, errno: %d (%s)", SD_TEST_FILE_PATH, errno, strerror(errno));
        
    //     // 尝试检查目录权限
    //     char dir_path[256];
    //     strncpy(dir_path, SD_TEST_FILE_PATH, sizeof(dir_path) - 1);
    //     dir_path[sizeof(dir_path) - 1] = '\0';
    //     char *last_slash = strrchr(dir_path, '/');
    //     if (last_slash) {
    //         *last_slash = '\0';
    //         if (stat(dir_path, &st) == 0) {
    //             ESP_LOGI(TAG, "目录 %s 存在，权限模式: %lo", dir_path, (unsigned long)st.st_mode);
    //         } else {
    //             ESP_LOGE(TAG, "目录 %s 不存在", dir_path);
    //         }
    //     }
        
    //     free(test_buffer);
    //     return;
    // }
    
    // ESP_LOGI(TAG, "文件创建成功，开始写入测试");
    
    // int64_t start_time = esp_timer_get_time();
    
    // // 写入测试数据
    // int total_blocks = (SD_TEST_FILE_SIZE_KB * 1024) / SD_TEST_BUFFER_SIZE;
    // ESP_LOGI(TAG, "准备写入 %d 个数据块，每块 %d 字节", total_blocks, SD_TEST_BUFFER_SIZE);
    
    // for (int i = 0; i < total_blocks; i++) {
    //     size_t written = fwrite(test_buffer, 1, SD_TEST_BUFFER_SIZE, f);
    //     if (written != SD_TEST_BUFFER_SIZE) {
    //         ESP_LOGE(TAG, "写入失败，期望 %d 字节，实际写入 %zu 字节", SD_TEST_BUFFER_SIZE, written);
    //         break;
    //     }
        
    //     // 每写入100个块打印一次进度
    //     if ((i + 1) % 100 == 0) {
    //         ESP_LOGI(TAG, "已写入 %d/%d 块", i + 1, total_blocks);
    //     }
    // }
    
    // fflush(f);  // 确保数据写入存储设备
    // int64_t end_time = esp_timer_get_time();
    // fclose(f);
    
    // int64_t duration_us = end_time - start_time;
    // double duration_s = duration_us / 1000000.0;
    // double data_size_mb = SD_TEST_FILE_SIZE_KB / 1024.0;
    // double write_speed_mbps = data_size_mb / duration_s;
    
    // ESP_LOGI(TAG, "写入测试完成:");
    // ESP_LOGI(TAG, "  - 数据大小: %.2f MB", data_size_mb);
    // ESP_LOGI(TAG, "  - 用时: %.3f 秒", duration_s);
    // ESP_LOGI(TAG, "  - 写入速度: %.2f MB/s", write_speed_mbps);
    // ESP_LOGI(TAG, "  - 写入速度: %.2f Mbps", write_speed_mbps * 8);
    
    // free(test_buffer);
}

// SD卡读取速度测试
static void sd_read_speed_test(void)
{
    // ESP_LOGI(TAG, "=== SD卡读取速度测试开始 ===");
    
    // uint8_t *test_buffer = malloc(SD_TEST_BUFFER_SIZE);
    // if (test_buffer == NULL) {
    //     ESP_LOGE(TAG, "内存分配失败");
    //     return;
    // }
    
    // FILE *f = fopen(SD_TEST_FILE_PATH, "rb");
    // if (f == NULL) {
    //     ESP_LOGE(TAG, "无法打开测试文件，请先运行写入测试");
    //     free(test_buffer);
    //     return;
    // }
    
    // int64_t start_time = esp_timer_get_time();
    
    // // 读取测试数据
    // int total_blocks = (SD_TEST_FILE_SIZE_KB * 1024) / SD_TEST_BUFFER_SIZE;
    // size_t total_read = 0;
    // for (int i = 0; i < total_blocks; i++) {
    //     size_t read_bytes = fread(test_buffer, 1, SD_TEST_BUFFER_SIZE, f);
    //     total_read += read_bytes;
    //     if (read_bytes != SD_TEST_BUFFER_SIZE) {
    //         ESP_LOGW(TAG, "读取字节数不完整，期望 %d，实际 %zu", SD_TEST_BUFFER_SIZE, read_bytes);
    //         break;
    //     }
    // }
    
    // int64_t end_time = esp_timer_get_time();
    // fclose(f);
    
    // int64_t duration_us = end_time - start_time;
    // double duration_s = duration_us / 1000000.0;
    // double data_size_mb = total_read / (1024.0 * 1024.0);
    // double read_speed_mbps = data_size_mb / duration_s;
    
    // ESP_LOGI(TAG, "读取测试完成:");
    // ESP_LOGI(TAG, "  - 数据大小: %.2f MB", data_size_mb);
    // ESP_LOGI(TAG, "  - 用时: %.3f 秒", duration_s);
    // ESP_LOGI(TAG, "  - 读取速度: %.2f MB/s", read_speed_mbps);
    // ESP_LOGI(TAG, "  - 读取速度: %.2f Mbps", read_speed_mbps * 8);
    
    // free(test_buffer);
}

// 底层SDMMC原始性能测试
static void sd_raw_performance_test(void)
{
    ESP_LOGI(TAG, "========== SD卡底层性能测试 ==========");
    
    if (g_sd_card == NULL) {
        ESP_LOGE(TAG, "SD卡未初始化");
        return;
    }
    
    // 打印详细SD卡信息
    ESP_LOGI(TAG, "SD卡扇区大小: %d 字节", g_sd_card->csd.sector_size);
    ESP_LOGI(TAG, "SD卡总容量: %.2f MB", (g_sd_card->csd.capacity * g_sd_card->csd.sector_size) / (1024.0 * 1024.0));
    ESP_LOGI(TAG, "SD卡总线宽度: %d 位", g_sd_card->log_bus_width);
    ESP_LOGI(TAG, "SD卡最大频率: %lu kHz", g_sd_card->max_freq_khz);
    ESP_LOGI(TAG, "SD卡实际频率: %d", g_sd_card->real_freq_khz);
    ESP_LOGI(TAG, "SD卡OCR: 0x%08lX", g_sd_card->ocr);
    ESP_LOGI(TAG, "SD卡类型: %s", g_sd_card->is_mmc ? "MMC" : "SD");
    
    // 打印SD卡制造商信息
    ESP_LOGI(TAG, "制造商ID: 0x%02X", g_sd_card->cid.mfg_id);
    ESP_LOGI(TAG, "产品名称: %.5s", g_sd_card->cid.name);
    ESP_LOGI(TAG, "产品版本: %d.%d", g_sd_card->cid.revision >> 4, g_sd_card->cid.revision & 0xF);
    ESP_LOGI(TAG, "生产日期: %02d/%04d", g_sd_card->cid.date & 0xF, 2000 + (g_sd_card->cid.date >> 4));
    
    // 计算测试参数
    size_t sector_size = g_sd_card->csd.sector_size;
    size_t test_sectors = (SD_TEST_FILE_SIZE_KB * 1024) / sector_size;
    size_t buffer_sectors = SD_TEST_BUFFER_SIZE / sector_size;
    
    ESP_LOGI(TAG, "测试扇区数: %zu", test_sectors);
    ESP_LOGI(TAG, "缓冲区扇区数: %zu", buffer_sectors);
    
    // 分配对齐的缓冲区
    uint8_t *test_buffer = malloc(buffer_sectors * sector_size);
    if (test_buffer == NULL) {
        ESP_LOGE(TAG, "内存分配失败");
        return;
    }
    
    // 填充测试数据
    for (size_t i = 0; i < buffer_sectors * sector_size; i++) {
        test_buffer[i] = i & 0xFF;
    }
    
    // 选择一个安全的起始扇区（避免文件系统区域）
    // 通常从扇区1000开始比较安全
    size_t start_sector = 1000;
    
    ESP_LOGI(TAG, "=== 底层写入速度测试 ===");
    int64_t start_time = esp_timer_get_time();
    
    size_t total_write_sectors = 0;
    for (size_t i = 0; i < test_sectors; i += buffer_sectors) {
        size_t sectors_to_write = (i + buffer_sectors <= test_sectors) ? buffer_sectors : (test_sectors - i);
        
        esp_err_t ret = sdmmc_write_sectors(g_sd_card, test_buffer, start_sector + i, sectors_to_write);
        if (ret != ESP_OK) {
            ESP_LOGE(TAG, "写入扇区失败: %s", esp_err_to_name(ret));
            break;
        }
        
        total_write_sectors += sectors_to_write;
        
        // 每写入100个缓冲区打印进度
        if ((i / buffer_sectors + 1) % 100 == 0) {
            ESP_LOGI(TAG, "已写入 %zu/%zu 个缓冲区", i / buffer_sectors + 1, test_sectors / buffer_sectors);
        }
    }
    
    int64_t end_time = esp_timer_get_time();
    int64_t duration_us = end_time - start_time;
    double duration_s = duration_us / 1000000.0;
    double data_size_mb = (total_write_sectors * sector_size) / (1024.0 * 1024.0);
    double write_speed_mbps = data_size_mb / duration_s;
    
    ESP_LOGI(TAG, "底层写入测试完成:");
    ESP_LOGI(TAG, "  - 写入扇区数: %zu", total_write_sectors);
    ESP_LOGI(TAG, "  - 数据大小: %.2f MB", data_size_mb);
    ESP_LOGI(TAG, "  - 用时: %.3f 秒", duration_s);
    ESP_LOGI(TAG, "  - 写入速度: %.2f MB/s", write_speed_mbps);
    ESP_LOGI(TAG, "  - 写入速度: %.2f Mbps", write_speed_mbps * 8);
    
    vTaskDelay(pdMS_TO_TICKS(100));
    
    ESP_LOGI(TAG, "=== 底层读取速度测试 ===");
    
    // 清空缓冲区
    memset(test_buffer, 0, buffer_sectors * sector_size);
    
    start_time = esp_timer_get_time();
    size_t total_read_sectors = 0;
    
    for (size_t i = 0; i < test_sectors; i += buffer_sectors) {
        size_t sectors_to_read = (i + buffer_sectors <= test_sectors) ? buffer_sectors : (test_sectors - i);
        
        esp_err_t ret = sdmmc_read_sectors(g_sd_card, test_buffer, start_sector + i, sectors_to_read);
        if (ret != ESP_OK) {
            ESP_LOGE(TAG, "读取扇区失败: %s", esp_err_to_name(ret));
            break;
        }
        
        total_read_sectors += sectors_to_read;
    }
    
    end_time = esp_timer_get_time();
    duration_us = end_time - start_time;
    duration_s = duration_us / 1000000.0;
    data_size_mb = (total_read_sectors * sector_size) / (1024.0 * 1024.0);
    double read_speed_mbps = data_size_mb / duration_s;
    
    ESP_LOGI(TAG, "底层读取测试完成:");
    ESP_LOGI(TAG, "  - 读取扇区数: %zu", total_read_sectors);
    ESP_LOGI(TAG, "  - 数据大小: %.2f MB", data_size_mb);
    ESP_LOGI(TAG, "  - 用时: %.3f 秒", duration_s);
    ESP_LOGI(TAG, "  - 读取速度: %.2f MB/s", read_speed_mbps);
    ESP_LOGI(TAG, "  - 读取速度: %.2f Mbps", read_speed_mbps * 8);
    
    free(test_buffer);
    ESP_LOGI(TAG, "========== SD卡底层性能测试完成 ==========");
}

// 综合SD卡性能测试
static void sd_performance_test(void)
{
//     ESP_LOGI(TAG, "========== SD卡性能测试 ==========");
//     ESP_LOGI(TAG, "测试文件大小: %d KB", SD_TEST_FILE_SIZE_KB);
//     ESP_LOGI(TAG, "缓冲区大小: %d 字节", SD_TEST_BUFFER_SIZE);
    
//     // 先进行底层性能测试
//     sd_raw_performance_test();
    
//     vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1秒
    
//     ESP_LOGI(TAG, "========== 文件系统性能测试 ==========");
    
//     // 写入速度测试
//     sd_write_speed_test();
    
//     vTaskDelay(pdMS_TO_TICKS(100)); // 短暂延迟
    
//     // 读取速度测试
//     sd_read_speed_test();
    
//     // 清理测试文件
//     if (remove(SD_TEST_FILE_PATH) == 0) {
//         ESP_LOGI(TAG, "测试文件已删除");
//     } else {
//         ESP_LOGW(TAG, "无法删除测试文件");
//     }
    
//     ESP_LOGI(TAG, "========== SD卡性能测试完成 ==========");
}

// 检查SD卡DDR模式支持
// static void check_ddr_support(sdmmc_card_t* card)
// {
//     ESP_LOGI(TAG, "========== DDR模式支持检查 ==========");
    
//     if (card == NULL) {
//         ESP_LOGE(TAG, "SD卡未初始化");
//         return;
//     }
    
//     // 检查卡类型
//     ESP_LOGI(TAG, "卡类型: %s", card->is_mmc ? "MMC/eMMC" : "SD");
    
//     // 检查SCR寄存器（SD卡专用）
//     if (!card->is_mmc) {
//         ESP_LOGI(TAG, "SD卡SCR信息:");
//         ESP_LOGI(TAG, "  - SCR结构版本: %d", card->scr.sd_spec);
//         ESP_LOGI(TAG, "  - 总线宽度支持: %s", 
//                  (card->scr.bus_width & (1 << 2)) ? "1位+4位" : "仅1位");  // BIT(2) = 4位总线
        
//         // 检查是否支持UHS-I (包括DDR50)
//         if (card->scr.sd_spec >= 2) {  // SD 3.0+
//             ESP_LOGI(TAG, "  - SD规范版本: 3.0+ (可能支持UHS-I模式)");
//         } else {
//             ESP_LOGI(TAG, "  - SD规范版本: 2.0 (不支持UHS-I模式)");
//         }
//     }
    
//     // 检查CSD寄存器信息
//     ESP_LOGI(TAG, "CSD寄存器信息:");
//     ESP_LOGI(TAG, "  - CSD版本: %d", card->csd.csd_ver);
//     ESP_LOGI(TAG, "  - 最大读取速度: %d", card->csd.tr_speed);
    
//     // 检查实际工作模式
//     ESP_LOGI(TAG, "当前工作状态:");
//     ESP_LOGI(TAG, "  - 实际总线宽度: %d位", card->log_bus_width);
//     ESP_LOGI(TAG, "  - 最大频率: %lu kHz", card->max_freq_khz);
//     ESP_LOGI(TAG, "  - 实际频率:%d kHz", card->real_freq_khz);
    
//     // 检查主机配置的DDR标志
//     ESP_LOGI(TAG, "主机DDR配置:");
//     if (card->host.flags & SDMMC_HOST_FLAG_DDR) {
//         ESP_LOGI(TAG, "  - 主机DDR模式: 已启用");
        
//         // 检查是否真的在DDR模式下工作
//         if (card->real_freq_khz > 25000) {  // 超过25MHz通常表示高速模式
//             ESP_LOGI(TAG, "  - DDR状态: 可能正在使用DDR模式");
//             ESP_LOGI(TAG, "  - 等效带宽: ~%.1f MHz", card->real_freq_khz * 2 / 1000.0);
//         } else {
//             ESP_LOGI(TAG, "  - DDR状态: 使用标准模式");
//         }
//     } else {
//         ESP_LOGI(TAG, "  - 主机DDR模式: 未启用");
//     }
    
//     // 性能预估
//     double theoretical_speed_mbps = 0;
//     if (card->host.flags & SDMMC_HOST_FLAG_DDR) {
//         theoretical_speed_mbps = (card->real_freq_khz * card->log_bus_width * 2) / (8 * 1000.0);
//     } else {
//         theoretical_speed_mbps = (card->real_freq_khz * card->log_bus_width) / (8 * 1000.0);
//     }
    
//     ESP_LOGI(TAG, "理论最大速度: %.2f MB/s", theoretical_speed_mbps);
//     ESP_LOGI(TAG, "========================================");
// }

// SD卡性能测试任务
static void sd_performance_test_task(void *param)
{
//     // 等待一段时间确保系统稳定，特别是SD卡文件系统完全准备好
//     ESP_LOGI(TAG, "SD卡性能测试任务启动，等待系统稳定...");
//     vTaskDelay(pdMS_TO_TICKS(3000));
    
//     ESP_LOGI(TAG, "开始执行SD卡性能测试任务");
//     sd_performance_test();
    
//     // 性能测试完成后，卸载SD卡
//     ESP_LOGI(TAG, "性能测试完成，开始卸载SD卡");
//     esp_vfs_fat_sdcard_unmount(MOUNT_POINT, g_sd_card);
//     ESP_LOGI(TAG, "SD卡已卸载");
    
//     // 如果使用了LDO power control，也需要释放
// #if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
//     if (g_pwr_ctrl_handle != NULL) {
//         esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(g_pwr_ctrl_handle);
//         if (ret != ESP_OK) {
//             ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
//         } else {
//             ESP_LOGI(TAG, "LDO power control driver deleted");
//         }
//         g_pwr_ctrl_handle = NULL;
//     }
// #endif
    
//     // 任务完成，删除自己
//     vTaskDelete(NULL);
}
// void init_display(void)
// {
//     FUNC_TIME_START(init_display);
    
//         bsp_enable_dsi_phy_power();

//         esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
//         esp_lcd_dsi_bus_config_t bus_config = JD9365_PANEL_BUS_DSI_2CH_CONFIG();
//         esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus);

//         ESP_LOGI(TAG, "Install MIPI DSI LCD control panel");
//         // we use DBI interface to send LCD commands and parameters
//         esp_lcd_dbi_io_config_t dbi_config = JD9365_PANEL_IO_DBI_CONFIG();
//         esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io);

//         esp_lcd_dpi_panel_config_t dpi_config = {
//             .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
//             .dpi_clock_freq_mhz = 46,
//             .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
//             .num_fbs = 1,
//             .video_timing = {
//                 .h_size = DISPLAY_WIDTH,
//                 .v_size = DISPLAY_HEIGHT,
//                 .hsync_pulse_width = 20,
//                 .hsync_back_porch = 20,
//                 .hsync_front_porch = 40,
//                 .vsync_pulse_width = 4,
//                 .vsync_back_porch = 12,
//                 .vsync_front_porch = 24,
//             },
//             .flags = {
//                 .use_dma2d = true,
//             },
//         };
//         jd9365_vendor_config_t vendor_config = {
//             .init_cmds = lcd_init_cmds,
//             .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]),
//             .mipi_config = {
//                 .dsi_bus = mipi_dsi_bus,
//                 .dpi_config = &dpi_config,
//                 .lane_num = 2,
//             },
//             .flags = {
//                 .use_mipi_interface = 1,
//             },
//         };

//         const esp_lcd_panel_dev_config_t lcd_dev_config = {
//             .reset_gpio_num = PIN_NUM_LCD_RST,
//             .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
//             .bits_per_pixel = 16,
//             .vendor_config = &vendor_config,
//         };
//         esp_lcd_new_panel_jd9365(io, &lcd_dev_config, &disp_panel);
//         esp_lcd_panel_reset(disp_panel);
//         esp_lcd_panel_init(disp_panel);
    
//     FUNC_TIME_END(init_display);
// }

/*==========小智+魔眼============ */
/* LCD size */
#define GC9A01_LCD_H_RES   (240)
#define GC9A01_LCD_V_RES   (240)
/* LCD settings */
#define GC9A01_LCD_SPI1_NUM         (SPI3_HOST)
#define GC9A01_LCD_SPI2_NUM         (SPI2_HOST)
#define GC9A01_LCD_PIXEL_CLK_HZ    (80 * 1000 * 1000)
#define GC9A01_LCD_CMD_BITS        (8)
#define GC9A01_LCD_PARAM_BITS      (8)
#define GC9A01_LCD_COLOR_SPACE     (ESP_LCD_COLOR_SPACE_RGB)
#define GC9A01_LCD_BITS_PER_PIXEL  (16)
#define GC9A01_LCD_DRAW_BUFF_DOUBLE (1)
#define GC9A01_LCD_DRAW_BUFF_HEIGHT (240)
#define GC9A01_LCD_BL_ON_LEVEL     (1)
/* LCD-SPI2 pins */
#define GC9A01_SPI2_LCD_GPIO_SCLK       (GPIO_NUM_38)
#define GC9A01_SPI2_LCD_GPIO_MOSI       (GPIO_NUM_39)
#define GC9A01_SPI2_LCD_GPIO_RST        (GPIO_NUM_40)
#define GC9A01_SPI2_LCD_GPIO_DC         (GPIO_NUM_0)
#define GC9A01_SPI2_LCD_GPIO_CS         (GPIO_NUM_NC)

#define GC9A01_SPI2_LCD_GPIO_BL         (GPIO_NUM_NC)
#define GC9A01_SPI2_LCD_GPIO_MISO       (GPIO_NUM_NC)

/* LCD-SPI1 pins */
#define GC9A01_SPI1_LCD_GPIO_SCLK       (GPIO_NUM_42)
#define GC9A01_SPI1_LCD_GPIO_MOSI       (GPIO_NUM_2)
#define GC9A01_SPI1_LCD_GPIO_RST        (GPIO_NUM_1)
#define GC9A01_SPI1_LCD_GPIO_DC         (GPIO_NUM_41)
#define GC9A01_SPI1_LCD_GPIO_CS         (GPIO_NUM_NC)

#define GC9A01_SPI1_LCD_GPIO_BL         (GPIO_NUM_NC)
#define GC9A01_SPI1_LCD_GPIO_MISO       (GPIO_NUM_NC)
//分辨率
#define DISPLAY_WIDTH   240
#define DISPLAY_HEIGHT  240
//镜像和轴交换：通常不需要镜像或轴交换，除非你的硬件设计需要特定的显示方向。
#define DISPLAY_MIRROR_X true
#define DISPLAY_MIRROR_Y false
#define DISPLAY_SWAP_XY false
//默认不启用颜色反转。
#define DISPLAY_INVERT_COLOR    true
//RGB顺序：LH128R-IG01使用RGB垂直条纹排列，因此设置为 LCD_RGB_ELEMENT_ORDER_RGB。
#define DISPLAY_RGB_ORDER  LCD_RGB_ELEMENT_ORDER_BGR
//偏移量：通常不需要偏移，除非你的显示屏有特定的显示区域限制。
#define DISPLAY_OFFSET_X  0
#define DISPLAY_OFFSET_Y  0
//背光输出取反：默认不取反，除非你的背光控制电路需要取反信号。
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true
#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC
#define DISPLAY_SPI_SCLK_HZ     (40 * 1000 * 1000)

/* LCD IO and panel */
static esp_lcd_panel_io_handle_t lcd_io1 = NULL;
static esp_lcd_panel_handle_t lcd_panel1 = NULL;
static esp_lcd_panel_io_handle_t lcd_io2 = NULL;
static esp_lcd_panel_handle_t lcd_panel2 = NULL;


// GC9A01-SPI2初始化-用于显示小智
void InitializeSpiEye1() {
    const spi_bus_config_t buscfg = {       
        .mosi_io_num = GC9A01_SPI1_LCD_GPIO_MOSI,
        .miso_io_num = GPIO_NUM_NC,
        .sclk_io_num = GC9A01_SPI1_LCD_GPIO_SCLK,
        .quadwp_io_num = GPIO_NUM_NC,
        .quadhd_io_num = GPIO_NUM_NC,
        .max_transfer_sz = GC9A01_LCD_H_RES * GC9A01_LCD_V_RES * sizeof(uint16_t), // 增大传输大小,
    };
    ESP_ERROR_CHECK(spi_bus_initialize(GC9A01_LCD_SPI1_NUM, &buscfg, SPI_DMA_CH_AUTO));
}

// GC9A01-SPI2初始化-用于显示魔眼
void InitializeGc9a01DisplayEye1() {
    ESP_LOGI(TAG, "Init GC9A01 display1");

    ESP_LOGI(TAG, "Install panel IO1");
    ESP_LOGD(TAG, "Install panel IO1");
    const esp_lcd_panel_io_spi_config_t io_config = {
        .cs_gpio_num = GC9A01_SPI1_LCD_GPIO_CS,
        .dc_gpio_num = GC9A01_SPI1_LCD_GPIO_DC,
        .spi_mode = 0,
        .pclk_hz = GC9A01_LCD_PIXEL_CLK_HZ,
        .trans_queue_depth = 10,
        .lcd_cmd_bits = GC9A01_LCD_CMD_BITS,
        .lcd_param_bits = GC9A01_LCD_PARAM_BITS,
        

    };
    esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)GC9A01_LCD_SPI1_NUM, &io_config, &lcd_io1);

    ESP_LOGD(TAG, "Install LCD1 driver");
    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = GC9A01_SPI1_LCD_GPIO_RST,
        .color_space = GC9A01_LCD_COLOR_SPACE,
        .bits_per_pixel = GC9A01_LCD_BITS_PER_PIXEL,
        
    };
    panel_config.rgb_endian = DISPLAY_RGB_ORDER;
    esp_lcd_new_panel_gc9a01(lcd_io1, &panel_config, &lcd_panel1);
    
    esp_lcd_panel_reset(lcd_panel1);
    esp_lcd_panel_init(lcd_panel1);
    esp_lcd_panel_invert_color(lcd_panel1, true);
    esp_lcd_panel_disp_on_off(lcd_panel1, true);
}

// GC9A01-SPI2初始化-用于显示魔眼
void InitializeSpiEye2() {
    const spi_bus_config_t buscfg = {       
        .mosi_io_num = GC9A01_SPI2_LCD_GPIO_MOSI,
        .miso_io_num = GPIO_NUM_NC,
        .sclk_io_num = GC9A01_SPI2_LCD_GPIO_SCLK,
        .quadwp_io_num = GPIO_NUM_NC,
        .quadhd_io_num = GPIO_NUM_NC,
        .max_transfer_sz = GC9A01_LCD_H_RES * GC9A01_LCD_V_RES * sizeof(uint16_t),
    };
    ESP_ERROR_CHECK(spi_bus_initialize(GC9A01_LCD_SPI2_NUM, &buscfg, SPI_DMA_CH_AUTO));
}

// GC9A01-SPI2初始化-用于显示魔眼
void InitializeGc9a01DisplayEye2() {
    ESP_LOGI(TAG, "Init GC9A01 display2");

    ESP_LOGI(TAG, "Install panel IO2");
    ESP_LOGD(TAG, "Install panel IO2");
    const esp_lcd_panel_io_spi_config_t io_config = {
        .cs_gpio_num = GC9A01_SPI2_LCD_GPIO_CS,
        .dc_gpio_num = GC9A01_SPI2_LCD_GPIO_DC,
        .spi_mode = 0,
        .pclk_hz = GC9A01_LCD_PIXEL_CLK_HZ,
        .trans_queue_depth = 10,
        .lcd_cmd_bits = GC9A01_LCD_CMD_BITS,
        .lcd_param_bits = GC9A01_LCD_PARAM_BITS,


    };
    esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)GC9A01_LCD_SPI2_NUM, &io_config, &lcd_io2);

    ESP_LOGD(TAG, "Install LCD2 driver");
    esp_lcd_panel_dev_config_t panel_config = {
        .reset_gpio_num = GC9A01_SPI2_LCD_GPIO_RST,
        .color_space = GC9A01_LCD_COLOR_SPACE,
        .bits_per_pixel = GC9A01_LCD_BITS_PER_PIXEL
    };
    panel_config.rgb_endian = DISPLAY_RGB_ORDER;
    esp_lcd_new_panel_gc9a01(lcd_io2, &panel_config, &lcd_panel2);
    esp_lcd_panel_reset(lcd_panel2);
    esp_lcd_panel_init(lcd_panel2);
    esp_lcd_panel_invert_color(lcd_panel2, true);
    esp_lcd_panel_disp_on_off(lcd_panel2, true);
    
}
void init_display(void)
{
    // FUNC_TIME_START(init_display);
        // 初始化第一块屏幕
        InitializeSpiEye1();
        InitializeSpiEye2();
        InitializeGc9a01DisplayEye1();
        InitializeGc9a01DisplayEye2();

    // FUNC_TIME_END(init_display);
}

void init_touch(void)
{
    // FUNC_TIME_START(init_touch);
    
    // esp_lcd_touch_handle_t tp;
    // esp_lcd_touch_config_t tp_cfg = {
    //     .x_max = DISPLAY_WIDTH,
    //     .y_max = DISPLAY_HEIGHT,
    //     .rst_gpio_num = GPIO_NUM_23,
    //     .int_gpio_num = GPIO_NUM_NC,
    //     .levels = {
    //         .reset = 0,
    //         .interrupt = 0,
    //     },
    //     .flags = {
    //         .swap_xy = 0,
    //         .mirror_x = 0,
    //         .mirror_y = 0,
    //     },
    // };
    // esp_lcd_panel_io_handle_t tp_io_handle = NULL;
    // esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
    // tp_io_config.scl_speed_hz = 400 * 1000;
    // ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle));
    // ESP_LOGI(TAG, "Initialize touch controller");
    // ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp));
    // const lvgl_port_touch_cfg_t touch_cfg = {
    //     .disp = lv_display_get_default(),
    //     .handle = tp,
    // };
    // lvgl_port_add_touch(&touch_cfg);
    // ESP_LOGI(TAG, "Touch panel initialized successfully");

    // FUNC_TIME_END(init_touch);
}


LV_FONT_DECLARE(font_awesome_30_4);
void init_lvgl(void)
{
    // Set the display to on
    ESP_LOGI(TAG, "Turning display on");
    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(lcd_panel1, true));
    // ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(lcd_panel2, true));

    ESP_LOGI(TAG, "Initialize LVGL library");
    lv_init();

    ESP_LOGI(TAG, "Initialize LVGL port");
    lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
    lvgl_port_init(&port_cfg);
}
void init_display1(void)
{
    ESP_LOGI(TAG, "Adding LCD1 display");
    const lvgl_port_display_cfg_t disp1_cfg = {
            .io_handle = lcd_io1,
            .panel_handle = lcd_panel1,
            .control_handle = NULL,
            .buffer_size = (uint32_t)(DISPLAY_WIDTH * 50),
            .double_buffer = true,
            .hres = (uint32_t)(DISPLAY_WIDTH),
            .vres = (uint32_t)(DISPLAY_HEIGHT),
            .monochrome = false,
            /* Rotation values must be same as used in esp_lcd for initial settings of the screen */
            .rotation = {
            .swap_xy = DISPLAY_SWAP_XY,
            .mirror_x = DISPLAY_MIRROR_X,
            .mirror_y = DISPLAY_MIRROR_Y,
        },
        .color_format = LV_COLOR_FORMAT_RGB565,

        .flags = {
            .buff_dma = true,
            .buff_spiram =false,//可能修改
            .sw_rotate = false,
            .swap_bytes = true,
            .full_refresh = false,
            .direct_mode = false,
        },
    };
    
    // const lvgl_port_display_dsi_cfg_t dpi_cfg = {
    //     .flags = {
    //         .avoid_tearing = false,
    //     }
    // };
        display1_ = lvgl_port_add_disp(&disp1_cfg);
    if (display1_ == NULL) {
        ESP_LOGE(TAG, "Failed to add display");
        return;
    }

    if (DISPLAY_OFFSET_X != 0 || DISPLAY_OFFSET_Y != 0) {
        lv_display_set_offset(display1_, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y);
    }

    screen1_ = lv_display_get_screen_active(display1_);
    // lv_obj_set_style_bg_color(screen1_, lv_color_hex(0x000000), 0); 
    // /* Create generic monitor */
    // lv_obj_t * sysmon = lv_sysmon_create(display1_);
        
    // /* Create performance monitor */
    // lv_sysmon_show_performance(NULL);  /* NULL = default display */
    
    // /* Create memory monitor */
    // #if LV_USE_MEM_MONITOR
    // lv_sysmon_show_memory(NULL);  /* Show memory usage and fragmentation */
    // #endif 
}

void init_display2(void)
{
    ESP_LOGI(TAG, "Adding LCD2 display");
    const lvgl_port_display_cfg_t disp2_cfg = {
            .io_handle = lcd_io2,
            .panel_handle = lcd_panel2,
            .control_handle = NULL,
            .buffer_size = (uint32_t)(DISPLAY_WIDTH * 50),
            .double_buffer = true,
            .hres = (uint32_t)(DISPLAY_WIDTH),
            .vres = (uint32_t)(DISPLAY_HEIGHT),
            .monochrome = false,
            /* Rotation values must be same as used in esp_lcd for initial settings of the screen */
            .rotation = {
            .swap_xy = DISPLAY_SWAP_XY,
            .mirror_x = DISPLAY_MIRROR_X,
            .mirror_y = DISPLAY_MIRROR_Y,
        },
        .color_format = LV_COLOR_FORMAT_RGB565,
        .flags = {
            .buff_dma = true,
            .buff_spiram =false,//可能修改
            .sw_rotate = false,
            .swap_bytes = true,
            .full_refresh = false,
            .direct_mode = false,
        },
    };
    
    // const lvgl_port_display_dsi_cfg_t dpi_cfg = {
    //     .flags = {
    //         .avoid_tearing = false,
    //     }
    // };
        display2_ = lvgl_port_add_disp(&disp2_cfg);
    if (display2_ == NULL) {
        ESP_LOGE(TAG, "Failed to add display");
        return;
    }

    if (DISPLAY_OFFSET_X != 0 || DISPLAY_OFFSET_Y != 0) {
        lv_display_set_offset(display2_, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y);
    }

    screen2_ = lv_display_get_screen_active(display2_);
    // lv_obj_set_style_bg_color(screen2_, lv_color_hex(0x000000), 0); 
    // /* Create generic monitor */
    // lv_obj_t * sysmon = lv_sysmon_create(display2_);
        
    // /* Create performance monitor */
    // lv_sysmon_show_performance(NULL);  /* NULL = default display */
    
    // /* Create memory monitor */
    // #if LV_USE_MEM_MONITOR
    // lv_sysmon_show_memory(NULL);  /* Show memory usage and fragmentation */
    // #endif 
}

void init_port_lvgl(void)
{
    // FUNC_TIME_START(init_port_lvgl);
    init_lvgl();
    ESP_LOGI(TAG, "1lvgl main remain heap: %ld bytes", esp_get_free_heap_size());
    init_display1();
    ESP_LOGI(TAG, "2lvgl main remain heap: %ld bytes", esp_get_free_heap_size());
    init_display2();
    //test display
    ESP_LOGI(TAG, "3lvgl main remain heap: %ld bytes", esp_get_free_heap_size());
    // FUNC_TIME_END(init_port_lvgl);

}

// void init_sd_card(void)
// {
//     FUNC_TIME_START(init_sd_card);
//     esp_err_t ret;

//     // Options for mounting the filesystem.
//     // If format_if_mount_failed is set to true, SD card will be partitioned and
//     // formatted in case when mounting fails.
//     esp_vfs_fat_sdmmc_mount_config_t mount_config = {
// #ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
//         .format_if_mount_failed = true,
// #else
//         .format_if_mount_failed = false,
// #endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
//         .max_files = 10,  // 增加最大文件数
//         .allocation_unit_size = 64 * 1024
//     };
//     const char mount_point[] = MOUNT_POINT;
//     ESP_LOGI(TAG, "Initializing SD card");

//     // Use settings defined above to initialize SD card and mount FAT filesystem.
//     // Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
//     // Please check its source code and implement error recovery when developing
//     // production applications.

//     ESP_LOGI(TAG, "Using SDMMC peripheral");

//     // By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
//     // For setting a specific frequency, use host.max_freq_khz (range 400kHz - 40MHz for SDMMC)
//     // Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
//     sdmmc_host_t host = SDMMC_HOST_DEFAULT();
    
//     // 尝试启用高速DDR模式 (40MHz DDR = 80MHz等效带宽)
//     host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;  // 40MHz
//     host.flags = SDMMC_HOST_FLAG_4BIT | SDMMC_HOST_FLAG_DDR;  // 4位总线 + DDR模式
    
//     // For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
//     // When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
//     // and the internal LDO power supply, we need to initialize the power supply first.
// #if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
//     sd_pwr_ctrl_ldo_config_t ldo_config = {
//         .ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
//     };

//     ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &g_pwr_ctrl_handle);
//     if (ret != ESP_OK) {
//         ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
//         return;
//     }
//     host.pwr_ctrl_handle = g_pwr_ctrl_handle;
// #endif

//     // This initializes the slot without card detect (CD) and write protect (WP) signals.
//     // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
//     sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();

//     // Set bus width to use:
// #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
//     slot_config.width = 4;
// #else
//     slot_config.width = 1;
// #endif

//     // On chips where the GPIOs used for SD card can be configured, set them in
//     // the slot_config structure:
// #ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
//     slot_config.clk = CONFIG_EXAMPLE_PIN_CLK;
//     slot_config.cmd = CONFIG_EXAMPLE_PIN_CMD;
//     slot_config.d0 = CONFIG_EXAMPLE_PIN_D0;
// #ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
//     slot_config.d1 = CONFIG_EXAMPLE_PIN_D1;
//     slot_config.d2 = CONFIG_EXAMPLE_PIN_D2;
//     slot_config.d3 = CONFIG_EXAMPLE_PIN_D3;
// #endif  // CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4
// #endif  // CONFIG_SOC_SDMMC_USE_GPIO_MATRIX

//     // Enable internal pullups on enabled pins. The internal pullups
//     // are insufficient however, please make sure 10k external pullups are
//     // connected on the bus. This is for debug / example purpose only.
//     slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;

//     ESP_LOGI(TAG, "Mounting filesystem");
//     ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &g_sd_card);

//     if (ret != ESP_OK) {
//         if (ret == ESP_FAIL) {
//             ESP_LOGE(TAG, "Failed to mount filesystem. "
//                      "If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
//         } else {
//             ESP_LOGE(TAG, "Failed to initialize the card (%s). "
//                      "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
// #ifdef CONFIG_EXAMPLE_DEBUG_PIN_CONNECTIONS
//             check_sd_card_pins(&config, pin_count);
// #endif
//         }
//         return;
//     }
//     ESP_LOGI(TAG, "Filesystem mounted");

//     // Card has been initialized, print its properties
//     sdmmc_card_print_info(stdout, g_sd_card);
    
//     // 检查DDR模式支持情况
//     check_ddr_support(g_sd_card);

//     // Use POSIX and C standard library functions to work with files:

//     // First create a file.
//     const char *file_hello = MOUNT_POINT"/hello.txt";
//     char data[EXAMPLE_MAX_CHAR_SIZE];
//     snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Hello", g_sd_card->cid.name);
//     ret = s_example_write_file(file_hello, data);
//     if (ret != ESP_OK) {
//         return;
//     }

//     const char *file_foo = MOUNT_POINT"/foo.txt";
//     // Check if destination file exists before renaming
//     struct stat st;
//     if (stat(file_foo, &st) == 0) {
//         // Delete it if it exists
//         unlink(file_foo);
//     }

//     // Rename original file
//     ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);
//     if (rename(file_hello, file_foo) != 0) {
//         ESP_LOGE(TAG, "Rename failed");
//         return;
//     }

//     ret = s_example_read_file(file_foo);
//     if (ret != ESP_OK) {
//         return;
//     }

//     // Format FATFS
// #ifdef CONFIG_EXAMPLE_FORMAT_SD_CARD
//     ret = esp_vfs_fat_sdcard_format(mount_point, card);
//     if (ret != ESP_OK) {
//         ESP_LOGE(TAG, "Failed to format FATFS (%s)", esp_err_to_name(ret));
//         return;
//     }

//     if (stat(file_foo, &st) == 0) {
//         ESP_LOGI(TAG, "file still exists");
//         return;
//     } else {
//         ESP_LOGI(TAG, "file doesn't exist, formatting done");
//     }
// #endif // CONFIG_EXAMPLE_FORMAT_SD_CARD

//     const char *file_nihao = MOUNT_POINT"/nihao.txt";
//     memset(data, 0, EXAMPLE_MAX_CHAR_SIZE);
//     snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Nihao", g_sd_card->cid.name);
//     ret = s_example_write_file(file_nihao, data);
//     if (ret != ESP_OK) {
//         return;
//     }

//     //Open file for reading
//     ret = s_example_read_file(file_nihao);
//     if (ret != ESP_OK) {
//         return;
//     }

//     // 不立即卸载SD卡，保持挂载状态以便后续的性能测试
//     ESP_LOGI(TAG, "SD卡保持挂载状态，准备进行性能测试");

//     // 注意：SD卡将在性能测试完成后由测试任务负责卸载
//     // 这里不调用 esp_vfs_fat_sdcard_unmount 和 sd_pwr_ctrl_del_on_chip_ldo

//     FUNC_TIME_END(init_sd_card);
// }

// 内存监控任务
static void memory_monitor_task(void *param)
{
    ESP_LOGI(TAG, "内存监控任务启动");
    
    while (1) {
        // 获取堆内存信息
        multi_heap_info_t heap_info;
        heap_caps_get_info(&heap_info, MALLOC_CAP_DEFAULT);
        
        // 获取PSRAM信息
        multi_heap_info_t psram_info;
        heap_caps_get_info(&psram_info, MALLOC_CAP_SPIRAM);
        
        // 获取内部RAM信息
        multi_heap_info_t internal_info;
        heap_caps_get_info(&internal_info, MALLOC_CAP_INTERNAL);
        
        // 获取DMA内存信息
        multi_heap_info_t dma_info;
        heap_caps_get_info(&dma_info, MALLOC_CAP_DMA);
        
        // 获取32位对齐内存信息
        multi_heap_info_t mem32_info;
        heap_caps_get_info(&mem32_info, MALLOC_CAP_32BIT);
        
        // 打印分隔线
        ESP_LOGI(TAG, "┌─────────────────────────────────────────────────────────────────────────────┐");
        ESP_LOGI(TAG, "│                           ESP32-P4 内存使用情况报告                           │");
        ESP_LOGI(TAG, "├─────────────────────────────────────────────────────────────────────────────┤");
        
        // 默认堆内存
        ESP_LOGI(TAG, "│ 默认堆内存 (MALLOC_CAP_DEFAULT):                                             │");
        ESP_LOGI(TAG, "│   总容量: %8zu KB  |  已用: %8zu KB  |  可用: %8zu KB        │", 
                 heap_info.total_allocated_bytes / 1024 + heap_info.total_free_bytes / 1024,
                 heap_info.total_allocated_bytes / 1024,
                 heap_info.total_free_bytes / 1024);
        ESP_LOGI(TAG, "│   最大块: %8zu KB  |  分配次数: %8zu  |  释放次数: %8zu      │",
                 heap_info.largest_free_block / 1024,
                 heap_info.allocated_blocks,
                 heap_info.free_blocks);
        ESP_LOGI(TAG, "├─────────────────────────────────────────────────────────────────────────────┤");
        
        // PSRAM (外部RAM)
        if (psram_info.total_free_bytes > 0 || psram_info.total_allocated_bytes > 0) {
            ESP_LOGI(TAG, "│ PSRAM 外部RAM (MALLOC_CAP_SPIRAM):                                           │");
            ESP_LOGI(TAG, "│   总容量: %8zu KB  |  已用: %8zu KB  |  可用: %8zu KB        │", 
                     (psram_info.total_allocated_bytes + psram_info.total_free_bytes) / 1024,
                     psram_info.total_allocated_bytes / 1024,
                     psram_info.total_free_bytes / 1024);
            ESP_LOGI(TAG, "│   最大块: %8zu KB  |  分配次数: %8zu  |  释放次数: %8zu      │",
                     psram_info.largest_free_block / 1024,
                     psram_info.allocated_blocks,
                     psram_info.free_blocks);
        } else {
            ESP_LOGI(TAG, "│ PSRAM 外部RAM (MALLOC_CAP_SPIRAM): 未检测到或未启用                          │");
        }
        ESP_LOGI(TAG, "├─────────────────────────────────────────────────────────────────────────────┤");
        
        // 内部RAM
        ESP_LOGI(TAG, "│ 内部RAM (MALLOC_CAP_INTERNAL):                                               │");
        ESP_LOGI(TAG, "│   总容量: %8zu KB  |  已用: %8zu KB  |  可用: %8zu KB        │", 
                 (internal_info.total_allocated_bytes + internal_info.total_free_bytes) / 1024,
                 internal_info.total_allocated_bytes / 1024,
                 internal_info.total_free_bytes / 1024);
        ESP_LOGI(TAG, "│   最大块: %8zu KB  |  分配次数: %8zu  |  释放次数: %8zu      │",
                 internal_info.largest_free_block / 1024,
                 internal_info.allocated_blocks,
                 internal_info.free_blocks);
        ESP_LOGI(TAG, "├─────────────────────────────────────────────────────────────────────────────┤");
        
        // DMA内存
        ESP_LOGI(TAG, "│ DMA内存 (MALLOC_CAP_DMA):                                                    │");
        ESP_LOGI(TAG, "│   总容量: %8zu KB  |  已用: %8zu KB  |  可用: %8zu KB        │", 
                 (dma_info.total_allocated_bytes + dma_info.total_free_bytes) / 1024,
                 dma_info.total_allocated_bytes / 1024,
                 dma_info.total_free_bytes / 1024);
        ESP_LOGI(TAG, "│   最大块: %8zu KB  |  分配次数: %8zu  |  释放次数: %8zu      │",
                 dma_info.largest_free_block / 1024,
                 dma_info.allocated_blocks,
                 dma_info.free_blocks);
        ESP_LOGI(TAG, "├─────────────────────────────────────────────────────────────────────────────┤");
        
        // 32位对齐内存
        ESP_LOGI(TAG, "│ 32位对齐内存 (MALLOC_CAP_32BIT):                                             │");
        ESP_LOGI(TAG, "│   总容量: %8zu KB  |  已用: %8zu KB  |  可用: %8zu KB        │", 
                 (mem32_info.total_allocated_bytes + mem32_info.total_free_bytes) / 1024,
                 mem32_info.total_allocated_bytes / 1024,
                 mem32_info.total_free_bytes / 1024);
        ESP_LOGI(TAG, "│   最大块: %8zu KB  |  分配次数: %8zu  |  释放次数: %8zu      │",
                 mem32_info.largest_free_block / 1024,
                 mem32_info.allocated_blocks,
                 mem32_info.free_blocks);
        ESP_LOGI(TAG, "├─────────────────────────────────────────────────────────────────────────────┤");
        
        // 系统级内存信息
        size_t free_heap = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
        size_t min_free_heap = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
        size_t free_internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
        size_t free_psram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
        
        ESP_LOGI(TAG, "│ 系统内存统计:                                                                 │");
        ESP_LOGI(TAG, "│   当前可用堆: %8zu KB  |  历史最小可用: %8zu KB                  │", 
                 free_heap / 1024, min_free_heap / 1024);
        ESP_LOGI(TAG, "│   内部RAM可用: %7zu KB  |  PSRAM可用: %10zu KB                  │", 
                 free_internal / 1024, free_psram / 1024);
        
        // 计算内存使用率
        size_t total_heap = heap_info.total_allocated_bytes + heap_info.total_free_bytes;
        size_t total_internal = internal_info.total_allocated_bytes + internal_info.total_free_bytes;
        size_t total_psram = psram_info.total_allocated_bytes + psram_info.total_free_bytes;
        
        if (total_heap > 0) {
            int heap_usage = (int)((heap_info.total_allocated_bytes * 100) / total_heap);
            ESP_LOGI(TAG, "│   默认堆使用率: %3d%%                                                        │", heap_usage);
        }
        
        if (total_internal > 0) {
            int internal_usage = (int)((internal_info.total_allocated_bytes * 100) / total_internal);
            ESP_LOGI(TAG, "│   内部RAM使用率: %3d%%                                                       │", internal_usage);
        }
        
        if (total_psram > 0) {
            int psram_usage = (int)((psram_info.total_allocated_bytes * 100) / total_psram);
            ESP_LOGI(TAG, "│   PSRAM使用率: %3d%%                                                         │", psram_usage);
        }
        
        // 获取任务信息
        UBaseType_t task_count = uxTaskGetNumberOfTasks();
        ESP_LOGI(TAG, "│   当前任务数量: %zu                                                           │", (size_t)task_count);
        
        // 获取系统运行时间
        int64_t uptime = esp_timer_get_time() / 1000000; // 转换为秒
        int hours = uptime / 3600;
        int minutes = (uptime % 3600) / 60;
        int seconds = uptime % 60;
        ESP_LOGI(TAG, "│   系统运行时间: %02d:%02d:%02d                                                 │", hours, minutes, seconds);
        
        ESP_LOGI(TAG, "└─────────────────────────────────────────────────────────────────────────────┘");
        ESP_LOGI(TAG, "");
        
        // 每5秒更新一次
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

void init_spiffs(){

    ESP_LOGI(TAG, "Initializing SPIFFS");

    esp_vfs_spiffs_conf_t conf = {
      .base_path = "/spiffs",
      .partition_label = NULL,
      .max_files = 8,
      .format_if_mount_failed = true
    };

    // Use settings defined above to initialize and mount SPIFFS filesystem.
    // Note: esp_vfs_spiffs_register is an all-in-one convenience function.
    esp_err_t ret = esp_vfs_spiffs_register(&conf);

    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount or format filesystem");
        } else if (ret == ESP_ERR_NOT_FOUND) {
            ESP_LOGE(TAG, "Failed to find SPIFFS partition");
        } else {
            ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
        }
        return;
    }
    //初始化lvgl读取文件系统接口
    // lv_fs_stdio_init();

    size_t total = 0, used = 0;
    ret = esp_spiffs_info(NULL, &total, &used);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
    } else {
        ESP_LOGI(TAG, "SPIFFS Partition size: total: %d, used: %d", total, used);
    }
}

static void read_hello_txt(void)
{
    ESP_LOGI(TAG, "Reading hello.txt");

    // Open for reading hello.txt
    FILE* f = fopen("/spiffs/hello.txt", "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open hello.txt");
        return;
    }

    char buf[64];
    memset(buf, 0, sizeof(buf));
    fread(buf, 1, sizeof(buf), f);
    fclose(f);

    // Display the read contents from the file
    ESP_LOGI(TAG, "Read from hello.txt: %s", buf);
}

void start_gif1(const char *gif_file_path)
{
    ESP_LOGI(TAG, "LVGL GIF 支持已启用，创建 GIF 对象");

    
    // 创建 LVGL GIF 对象
    gif_img1 = lv_gif_create(screen1_);
    if (gif_img1 == NULL) {
        ESP_LOGE(TAG, "创建 GIF 对象失败");
        return;
    }
    
    // 设置 GIF 文件路径
    ESP_LOGI(TAG, "尝试设置GIF源文件: %s", gif_file_path);
    lv_gif_set_src(gif_img1, gif_file_path);
    
    // 检查GIF是否成功加载
    if (lv_gif_is_loaded(gif_img1)) {
        ESP_LOGI(TAG, "GIF加载成功！");
        
        // 居中显示 GIF
        lv_obj_center(gif_img1);
        
        // 设置可见性
        lv_obj_clear_flag(gif_img1, LV_OBJ_FLAG_HIDDEN);

        ESP_LOGI(TAG, "GIF 文件已加载并开始播放: %s", gif_file_path);
        // fclose(f);
    } else {
        ESP_LOGE(TAG, "GIF加载失败！文件路径: %s", gif_file_path);
        
        // 尝试不同的路径格式
        ESP_LOGI(TAG, "尝试使用无驱动器前缀的路径: %s", GIF_FILE_PATH);
        lv_gif_set_src(gif_img1, GIF_FILE_PATH);
        
        if (lv_gif_is_loaded(gif_img1)) {
            ESP_LOGI(TAG, "使用无前缀路径加载GIF成功！");
            lv_obj_center(gif_img1);
            lv_obj_clear_flag(gif_img1, LV_OBJ_FLAG_HIDDEN);
        } else {
            ESP_LOGE(TAG, "两种路径格式都无法加载GIF文件");
            
            // 如果GIF加载失败，创建一个错误信息显示
            lv_obj_del(gif_img1);
            gif_img1 = lv_label_create(screen1_);
            lv_label_set_text(gif_img1, "GIF file load failed\nPlease check:\n1. File exists\n2. File format is correct");
            lv_obj_center(gif_img1);
            lv_obj_set_style_text_color(gif_img1, lv_color_white(), 0);
            lv_obj_set_style_text_align(gif_img1, LV_TEXT_ALIGN_CENTER, 0);
        }
    }

}

void start_gif2(const char *gif_file_path)
{
    ESP_LOGI(TAG, "LVGL GIF 支持已启用，创建 GIF 对象");

    
    // 创建 LVGL GIF 对象
    gif_img2 = lv_gif_create(screen2_);
    if (gif_img2 == NULL) {
        ESP_LOGE(TAG, "创建 GIF 对象失败");
        return;
    }
    
    // 设置 GIF 文件路径
    ESP_LOGI(TAG, "尝试设置GIF源文件: %s", gif_file_path);
    // FUNC_TIME_START(lv_gif_set_src);
    lv_gif_set_src(gif_img2, gif_file_path);
    // FUNC_TIME_END(lv_gif_set_src);
    
    // 检查GIF是否成功加载
    if (lv_gif_is_loaded(gif_img2)) {
        ESP_LOGI(TAG, "GIF加载成功！");
        
        // 居中显示 GIF
        // lv_obj_center(gif_img2);
        
        // 设置可见性
        lv_obj_clear_flag(gif_img2, LV_OBJ_FLAG_HIDDEN);

        ESP_LOGI(TAG, "GIF 文件已加载并开始播放: %s", gif_file_path);
        // fclose(f);
    } else {
        ESP_LOGE(TAG, "GIF加载失败！文件路径: %s", LVGL_GIF_FILE_PATH);
        
        // 尝试不同的路径格式
        ESP_LOGI(TAG, "尝试使用无驱动器前缀的路径: %s", GIF_FILE_PATH);
        lv_gif_set_src(gif_img2, LVGL_GIF_FILE_PATH);
        
        if (lv_gif_is_loaded(gif_img2)) {
            ESP_LOGI(TAG, "使用无前缀路径加载GIF成功！");
            lv_obj_center(gif_img2);
            lv_obj_clear_flag(gif_img2, LV_OBJ_FLAG_HIDDEN);
        } else {
            ESP_LOGE(TAG, "两种路径格式都无法加载GIF文件");
            
            // 如果GIF加载失败，创建一个错误信息显示
            lv_obj_del(gif_img2);
            gif_img2 = lv_label_create(screen2_);
            lv_label_set_text(gif_img2, "GIF file load failed\nPlease check:\n1. File exists\n2. File format is correct");
            lv_obj_center(gif_img2);
            lv_obj_set_style_text_color(gif_img2, lv_color_white(), 0);
            lv_obj_set_style_text_align(gif_img2, LV_TEXT_ALIGN_CENTER, 0);
        }
    }

}

#include "esp_flash.h"

// 读取Flash中指定地址的数据
esp_err_t read_flash_data(uint32_t flash_address, uint8_t* buffer, size_t length)
{
    if (buffer == NULL || length == 0) {
        return ESP_ERR_INVALID_ARG;
    }
    
    // 使用esp_flash_read读取数据
    esp_err_t err = esp_flash_read(esp_flash_default_chip, buffer, flash_address, length);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read flash data at 0x%08lx, error: %s", 
                 flash_address, esp_err_to_name(err));
        return err;
    }
    
    ESP_LOGI(TAG, "Successfully read %d bytes from flash address 0x%08lx", 
             (int)length, flash_address);
    return ESP_OK;
}

// 读取图片数据并显示
void show_image_from_flash(uint32_t flash_address, size_t image_size)
{
    ESP_LOGI(TAG, "Reading image from flash address: 0x%08lx, size: %d bytes", 
             flash_address, (int)image_size);
    
    // 分配内存存储图片数据
    // 优先使用PSRAM，如果没有PSRAM则使用内部内存
    uint8_t* image_data = NULL;
    if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > image_size) {
        image_data = heap_caps_malloc(image_size, MALLOC_CAP_SPIRAM);
        ESP_LOGI(TAG, "Allocated %d bytes in PSRAM", (int)image_size);
    } else {
        image_data = malloc(image_size);
        ESP_LOGI(TAG, "Allocated %d bytes in internal memory", (int)image_size);
    }
    
    if (image_data == NULL) {
        ESP_LOGE(TAG, "Failed to allocate memory for image data");
        return;
    }
    
    // 从Flash读取图片数据
    esp_err_t err = read_flash_data(flash_address, image_data, image_size);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read image data from flash");
        free(image_data);
        return;
    }
    
    // 打印前几个字节作为验证
    ESP_LOGI(TAG, "First 16 bytes of image data:");
    for (int i = 0; i < 16 && i < image_size; i++) {
        printf("0x%02x ", image_data[i]);
    }
    printf("\n");
    
    // 创建LVGL图片对象显示读取成功的信息
    lv_obj_t* label = lv_label_create(screen1_);
    if (label) {
        lv_label_set_text_fmt(label, "Image loaded\nSize: %d bytes\nFrom: 0x%08lx", 
                              (int)image_size, flash_address);
        lv_obj_center(label);
    }
    
    // 注意：这里为了演示只显示信息，实际图片显示需要解码处理
    // 如果需要长期保存数据，不要立即释放内存
    // free(image_data);
}

// 改进的Flash读取函数，包含更多调试信息
void show_image_from_flash_debug(uint32_t flash_address, size_t image_size)
{
    ESP_LOGI(TAG, "=== Reading image from flash ===");
    ESP_LOGI(TAG, "Flash address: 0x%08lx", flash_address);
    ESP_LOGI(TAG, "Image size: %d bytes", (int)image_size);
    
    // 分配内存存储图片数据
    uint8_t* image_data = NULL;
    if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > image_size) {
        image_data = heap_caps_malloc(image_size, MALLOC_CAP_SPIRAM);
        ESP_LOGI(TAG, "Allocated %d bytes in PSRAM", (int)image_size);
    } else {
        image_data = malloc(image_size);
        ESP_LOGI(TAG, "Allocated %d bytes in internal memory", (int)image_size);
    }
    
    if (image_data == NULL) {
        ESP_LOGE(TAG, "Failed to allocate memory for image data");
        return;
    }
    
    // 从Flash读取图片数据
    ESP_LOGI(TAG, "Reading data from flash...");
    esp_err_t err = esp_flash_read(esp_flash_default_chip, image_data, flash_address, image_size);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read image data from flash: %s", esp_err_to_name(err));
        free(image_data);
        return;
    }
    
    ESP_LOGI(TAG, "Successfully read %d bytes from flash", (int)image_size);
    
    // 详细分析读取到的数据
    ESP_LOGI(TAG, "=== Data Analysis ===");
    
    // 检查前64字节
    ESP_LOGI(TAG, "First 64 bytes:");
    for (int i = 0; i < 64 && i < image_size; i++) {
        if (i % 16 == 0) {
            printf("\n[%04x] ", i);
        }
        printf("%02x ", image_data[i]);
    }
    printf("\n");
    
    // 检查文件头标识
    if (image_size >= 4) {
        ESP_LOGI(TAG, "File signature check:");
        ESP_LOGI(TAG, "  Bytes 0-3: 0x%02x 0x%02x 0x%02x 0x%02x", 
                 image_data[0], image_data[1], image_data[2], image_data[3]);
        
        // 常见文件格式检查
        if (image_data[0] == 0xFF && image_data[1] == 0xD8 && image_data[2] == 0xFF) {
            ESP_LOGI(TAG, "  Detected: JPEG file");
        } else if (image_data[0] == 'G' && image_data[1] == 'I' && image_data[2] == 'F') {
            ESP_LOGI(TAG, "  Detected: GIF file");
        } else if (image_data[0] == 0x89 && image_data[1] == 'P' && image_data[2] == 'N' && image_data[3] == 'G') {
            ESP_LOGI(TAG, "  Detected: PNG file");
        } else if (image_data[0] == 'B' && image_data[1] == 'M') {
            ESP_LOGI(TAG, "  Detected: BMP file");
        } else {
            ESP_LOGI(TAG, "  Unknown file format");
        }
    }
    
    // 检查最后几个字节
    if (image_size > 16) {
        ESP_LOGI(TAG, "Last 16 bytes:");
        for (int i = image_size - 16; i < image_size; i++) {
            if ((i - (image_size - 16)) % 16 == 0) {
                printf("\n[%04x] ", i);
            }
            printf("%02x ", image_data[i]);
        }
        printf("\n");
    }
    
    // 创建LVGL对象显示信息
    lv_obj_t* label = lv_label_create(screen1_);
    if (label) {
        lv_label_set_text_fmt(label, "Flash Read Complete\n"
                              "Address: 0x%08lx\n"
                              "Size: %d bytes\n"
                              "Status: Success", 
                              flash_address, (int)image_size);
        lv_obj_center(label);
    }
    
    // 保存数据供后续使用
    static uint8_t* saved_image_data = NULL;
    static size_t saved_image_size = 0;
    
    if (saved_image_data) {
        free(saved_image_data);
    }
    saved_image_data = image_data;
    saved_image_size = image_size;
    
    ESP_LOGI(TAG, "=== Flash read operation completed ===");
}

// 校验Flash数据完整性的函数
bool verify_flash_data_integrity(uint32_t flash_address, const uint8_t* expected_data, size_t data_size)
{
    ESP_LOGI(TAG, "Verifying flash data integrity at 0x%08lx, size: %d bytes", 
             flash_address, (int)data_size);
    
    // 分配缓冲区读取数据
    uint8_t* read_buffer = malloc(data_size);
    if (read_buffer == NULL) {
        ESP_LOGE(TAG, "Failed to allocate buffer for verification");
        return false;
    }
    
    // 从Flash读取数据
    esp_err_t err = esp_flash_read(esp_flash_default_chip, read_buffer, flash_address, data_size);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read flash for verification: %s", esp_err_to_name(err));
        free(read_buffer);
        return false;
    }
    
    // 比较数据
    bool is_match = (memcmp(read_buffer, expected_data, data_size) == 0);
    
    if (is_match) {
        ESP_LOGI(TAG, "Flash data verification: PASSED");
    } else {
        ESP_LOGE(TAG, "Flash data verification: FAILED");
        
        // 显示不匹配的数据位置
        int mismatch_count = 0;
        for (int i = 0; i < data_size && mismatch_count < 10; i++) {
            if (read_buffer[i] != expected_data[i]) {
                ESP_LOGE(TAG, "Mismatch at offset 0x%04x: expected 0x%02x, got 0x%02x", 
                         i, expected_data[i], read_buffer[i]);
                mismatch_count++;
            }
        }
    }
    
    free(read_buffer);
    return is_match;
}




void spiffs_test()
{ 
    // size_t total = 0, used = 0;
    // esp_err_t ret = esp_spiffs_info(NULL, &total, &used);
    // if (ret != ESP_OK) {
    //     ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
    // } else {
    //     ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
    // }

    /* The following calls demonstrate reading files from the generated SPIFFS
     * image. The images should contain the same files and contents as the spiffs_image directory.
     */

    // Read and display the contents of a small text file (hello.txt)
    // read_hello_txt();



    // // All done, unmount partition and disable SPIFFS
    // esp_vfs_spiffs_unregister(NULL);
    // ESP_LOGI(TAG, "SPIFFS unmounted");


}

void lv_read_img_from_spiffs(const char *filename, uint8_t *buf, size_t buf_size)
{
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return;
    }
    size_t bytes_read = fread(buf, 1, buf_size, fp);
    fclose(fp);
}
void app_gif_task(void *pvParameters)
{
    start_gif2(SPIFFS_PATH"/Agree.gif");
    start_gif1( SPIFFS_PATH"/Angry.gif");
    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
#define FLASH_ADDRESS 0x200000
#define DATA_LENGTH 16  // 读取前16个字节进行验证
#include "esp_partition.h"
#include "esp_spi_flash.h"
void verify_flash_data(void)
{
    // 分配缓冲区存储读取的数据
    uint8_t read_data[DATA_LENGTH];
    
    // 从指定地址读取数据
    esp_err_t ret = esp_flash_read(esp_flash_default_chip, read_data, FLASH_ADDRESS, DATA_LENGTH);
    
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Flash read failed: %s", esp_err_to_name(ret));
        return;
    }
    
    // 打印读取的数据
    ESP_LOGI(TAG, "Data read from flash address 0x%06X:", FLASH_ADDRESS);
    for (int i = 0; i < DATA_LENGTH; i++) {
        printf("0x%02x ", read_data[i]);
        if ((i + 1) % 8 == 0) printf("\n");
    }
    printf("\n");
    
    // 验证 JPEG 文件头 (0xFFD8FFE0)
    if (read_data[0] == 0xFF && read_data[1] == 0xD8 && 
        read_data[2] == 0xFF && read_data[3] == 0xE0) {
        ESP_LOGI(TAG, "Verification successful: JPEG header found at address 0x%06X", FLASH_ADDRESS);
    } else {
        ESP_LOGW(TAG, "Verification failed: JPEG header not found");
        // 添加更多调试信息
        ESP_LOGW(TAG, "Expected JPEG header: 0xFF 0xD8 0xFF 0xE0");
        ESP_LOGW(TAG, "Actual data: 0x%02X 0x%02X 0x%02X 0x%02X", 
                 read_data[0], read_data[1], read_data[2], read_data[3]);
    }
}

// 如果你想读取整个文件内容进行验证，可以使用以下函数
void read_full_file_info(void)
{
    // JPEG文件的标识信息
    uint8_t jpeg_signature[4];
    
    // 读取JPEG文件头
    esp_err_t ret = esp_flash_read(esp_flash_default_chip, jpeg_signature, FLASH_ADDRESS, 4);
    
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read flash: %s", esp_err_to_name(ret));
        return;
    }
    
    ESP_LOGI(TAG, "First 4 bytes: 0x%02X 0x%02X 0x%02X 0x%02X", 
             jpeg_signature[0], jpeg_signature[1], 
             jpeg_signature[2], jpeg_signature[3]);
    
    // 检查JPEG文件头
    if (jpeg_signature[0] == 0xFF && jpeg_signature[1] == 0xD8) {
        ESP_LOGI(TAG, "File successfully written to flash at 0x%06X", FLASH_ADDRESS);
    } else {
        ESP_LOGE(TAG, "File write verification failed");
    }
}

void show_flash_partition_info(void)
{
    ESP_LOGI(TAG, "=== Flash Partition Information ===");
    
    // 获取Flash芯片大小
    uint32_t flash_size;
    esp_err_t err = esp_flash_get_size(esp_flash_default_chip, &flash_size);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "Flash size: %d MB", (int)(flash_size / (1024 * 1024)));
    } else {
        ESP_LOGE(TAG, "Failed to get flash size: %s", esp_err_to_name(err));
    }
    
    // 检查目标地址是否在有效范围内
    if (FLASH_ADDRESS >= flash_size) {
        ESP_LOGE(TAG, "Target address 0x%06X is out of flash range (0x%08X)", 
                 FLASH_ADDRESS, (unsigned int)flash_size);
    } else {
        ESP_LOGI(TAG, "Target address 0x%06X is within flash range", FLASH_ADDRESS);
    }
    
    // 列出所有分区
    esp_partition_iterator_t iterator = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
    while (iterator != NULL) {
        const esp_partition_t* partition = esp_partition_get(iterator);
        ESP_LOGI(TAG, "Partition: %s, type: %d, subtype: %d, address: 0x%08x, size: 0x%08x", 
                 partition->label, partition->type, partition->subtype, 
                 (unsigned int)partition->address, (unsigned int)partition->size);
        iterator = esp_partition_next(iterator);
    }
    esp_partition_iterator_release(iterator);
}
// 添加新的函数来通过分区读取数据
void read_data_from_ui_partition(void)
{
    ESP_LOGI(TAG, "=== Reading data from UI partition ===");
    
    // 查找ui分区
    const esp_partition_t* partition = esp_partition_find_first(
        ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "ui");
    
    if (partition == NULL) {
        ESP_LOGE(TAG, "UI partition not found");
        return;
    }
    
    ESP_LOGI(TAG, "Found UI partition: address=0x%08x, size=0x%08x", 
             (unsigned int)partition->address, (unsigned int)partition->size);
    
    // 读取分区开头的数据
    const size_t read_size = 32;
    uint8_t* buffer = malloc(read_size);
    if (buffer == NULL) {
        ESP_LOGE(TAG, "Failed to allocate buffer");
        return;
    }
    
    esp_err_t err = esp_partition_read(partition, 0, buffer, read_size);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read partition: %s", esp_err_to_name(err));
        free(buffer);
        return;
    }
    
    ESP_LOGI(TAG, "Data read from UI partition:");
    for (int i = 0; i < read_size; i++) {
        if (i % 16 == 0) {
            printf("\n[%04x] ", i);
        }
        printf("%02x ", buffer[i]);
    }
    printf("\n");
    
    // 检查JPEG文件头
    if (buffer[0] == 0xFF && buffer[1] == 0xD8) {
        ESP_LOGI(TAG, "JPEG header verified in UI partition");
    } else {
        ESP_LOGW(TAG, "No JPEG header found. Data may not be correctly written");
        ESP_LOGW(TAG, "First 4 bytes as ASCII: '%.*s'", 4, buffer);
    }
    
    free(buffer);
}

// 更新verify_flash_data函数以使用分区API
void verify_flash_data_via_partition(void)
{
    ESP_LOGI(TAG, "=== Verifying flash data via partition API ===");
    
    // 查找ui分区
    const esp_partition_t* partition = esp_partition_find_first(
        ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "ui");
    
    if (partition == NULL) {
        ESP_LOGE(TAG, "UI partition not found");
        return;
    }
    
    // 读取前几个字节
    uint8_t header[16];
    esp_err_t err = esp_partition_read(partition, 0, header, sizeof(header));
    
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read partition: %s", esp_err_to_name(err));
        return;
    }
    
    // 打印读取的数据
    ESP_LOGI(TAG, "Data read from UI partition (address 0x%08x):", (unsigned int)partition->address);
    for (int i = 0; i < sizeof(header); i++) {
        printf("0x%02x ", header[i]);
        if ((i + 1) % 8 == 0) printf("\n");
    }
    if (sizeof(header) % 8 != 0) printf("\n");
    
    // 验证 JPEG 文件头
    if (header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF) {
        ESP_LOGI(TAG, "Verification successful: JPEG header found in UI partition");
    } else {
        ESP_LOGW(TAG, "Verification failed: JPEG header not found in UI partition");
        ESP_LOGW(TAG, "Expected JPEG header: 0xFF 0xD8 0xFF");
        ESP_LOGW(TAG, "Actual data: 0x%02X 0x%02X 0x%02X", header[0], header[1], header[2]);
    }
}
void app_main(void)
{
    ESP_LOGI(TAG, "=== Video Codec Test Application ===");
    ESP_LOGI(TAG, "0app main remain heap: %ld bytes", esp_get_free_heap_size());
    
    // 初始化LVGL和显示
    init_display();
    ESP_LOGI(TAG, "1app main remain heap: %ld bytes", esp_get_free_heap_size());

    // 初始化LVGL
    init_port_lvgl();
    ESP_LOGI(TAG, "2app main remain heap: %ld bytes", esp_get_free_heap_size());
    
    // 初始化SD卡
    // init_sd_card();

   //  xTaskCreate(memory_monitor_task, "Memory Monitor", 4096, NULL, 5, NULL);
    //初始化文件系统
    // init_spiffs();
    ESP_LOGI(TAG, "3app main remain heap: %ld bytes", esp_get_free_heap_size());

    ESP_LOGI(TAG, "app main remain heap: %ld bytes", esp_get_free_heap_size());
    // 测试: 预加载多帧JPEG播放（推荐方式）
    ESP_LOGI(TAG, "\n🎬 Test 2: Preloaded JPEG Playback");
    InitializeDisplayTask();

    decode_task();
    // vTaskDelay(pdMS_TO_TICKS(2000));
    
    ESP_LOGI(TAG, "\n✅ All tests completed!");
}